Code
import requests
import pandas as pd
import geopandasOpenSky provides api to get data for flights in progress. It is rate limited
import requests
import pandas as pd
import geopandasdef fetch_opensky_data():
url = "https://opensky-network.org/api/states/all"
response = requests.get(url)
data = response.json()
columns = [
"icao24", "callsign", "origin_country", "time_position", "last_contact",
"longitude", "latitude", "baro_altitude", "on_ground", "velocity",
"heading", "vertical_rate", "sensors", "geo_altitude", "squawk",
"spi", "position_source"
]
df_raw = pd.DataFrame(data['states'], columns=columns)
return (
df_raw
.assign(
time_position=pd.to_datetime(df_raw["time_position"], unit="s"),
last_contact=pd.to_datetime(df_raw["last_contact"], unit="s"),
)
)
df_flights = fetch_opensky_data()
df_flihts_non_nan = df_flights.dropna(subset=["longitude", "latitude"])
gdf = geopandas.GeoDataFrame(
df_flihts_non_nan,
geometry=geopandas.points_from_xy(df_flihts_non_nan.longitude, df_flihts_non_nan.latitude),
crs="EPSG:4326",
)
gdf.explore(fullscreen=True, tooltip=False, popup=True)Flights in world at notebook time
(
df_flights
.groupby("origin_country")
.agg(num_flights=("icao24", "count"))
.sort_values("num_flights", ascending=False)
.head(20)
)| num_flights | |
|---|---|
| origin_country | |
| United States | 1549 |
| Australia | 282 |
| Germany | 257 |
| Ireland | 253 |
| China | 245 |
| Turkey | 241 |
| India | 214 |
| United Kingdom | 180 |
| Japan | 162 |
| France | 158 |
| Malta | 155 |
| Spain | 150 |
| Canada | 146 |
| Austria | 142 |
| Kingdom of the Netherlands | 114 |
| United Arab Emirates | 110 |
| Switzerland | 97 |
| Poland | 87 |
| Republic of Korea | 73 |
| Thailand | 65 |
Top 20 countries with most flights
For reference
df_flights| icao24 | callsign | origin_country | time_position | last_contact | longitude | latitude | baro_altitude | on_ground | velocity | heading | vertical_rate | sensors | geo_altitude | squawk | spi | position_source | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 39de4f | TVF13AU | France | 2025-05-23 05:22:23 | 2025-05-23 05:22:24 | 15.2441 | 43.6133 | 11574.78 | False | 224.35 | 302.45 | -0.65 | None | 11666.22 | 2053 | False | 0 |
| 1 | 801636 | VTAQL | India | 2025-05-23 05:22:25 | 2025-05-23 05:22:25 | 72.2426 | 19.5978 | 5204.46 | False | 173.03 | 138.01 | -4.88 | None | 5394.96 | None | False | 0 |
| 2 | 39de4b | TVF72TD | France | 2025-05-23 05:22:24 | 2025-05-23 05:22:25 | 12.1106 | 52.2264 | 8686.80 | False | 187.43 | 261.16 | 9.75 | None | 8496.30 | 1000 | False | 0 |
| 3 | 39de4a | TVF46CN | France | 2025-05-23 05:22:24 | 2025-05-23 05:22:25 | -2.8372 | 45.7037 | 11894.82 | False | 244.08 | 221.92 | 0.00 | None | 12047.22 | 7647 | False | 0 |
| 4 | 39de4c | TVF30BT | France | 2025-05-23 05:22:25 | 2025-05-23 05:22:25 | 1.7482 | 46.7946 | 11277.60 | False | 239.05 | 192.30 | 0.00 | None | 11353.80 | 7653 | False | 0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 5942 | aa781f | CKS220 | United States | 2025-05-23 05:22:22 | 2025-05-23 05:22:22 | -152.8475 | 64.3178 | 10972.80 | False | 249.00 | 258.92 | 0.00 | None | 10805.16 | 5246 | True | 0 |
| 5943 | a4359b | UPS921 | United States | 2025-05-23 05:22:24 | 2025-05-23 05:22:24 | -92.9572 | 38.3046 | 10675.62 | False | 273.22 | 88.92 | 0.00 | None | 10949.94 | 7252 | False | 0 |
| 5944 | a0c7b3 | ABX3114 | United States | 2025-05-23 05:22:25 | 2025-05-23 05:22:25 | -81.9548 | 42.5158 | 11277.60 | False | 255.05 | 85.14 | -0.33 | None | 11224.26 | 6264 | False | 0 |
| 5945 | 458664 | CAT323 | Denmark | 2025-05-23 05:22:24 | 2025-05-23 05:22:25 | 10.7519 | 52.8907 | 11887.20 | False | 241.10 | 162.11 | 0.00 | None | 11757.66 | 3510 | False | 0 |
| 5946 | 458666 | VKG1604 | Denmark | 2025-05-23 05:22:25 | 2025-05-23 05:22:25 | 10.6386 | 59.9969 | 5128.26 | False | 180.01 | 187.39 | 1.95 | None | 4945.38 | 4515 | False | 0 |
5947 rows × 17 columns